
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:mobile_scanner/mobile_scanner.dart';
import 'package:o2oa_all_platform/common/index.dart';
import 'package:permission_handler/permission_handler.dart';

import '../../apps/cms/cms_document/index.dart';
import '../../home/default_index/scan_login/index.dart';
import '../portal/index.dart';
import '../process_webview/index.dart';
import 'index.dart';

class ScanPage extends StatefulWidget {
  const ScanPage({Key? key}) : super(key: key);

  /// 扫描二维码业务
  ///
  /// [O2ScanCallback] 是给 jsapi 返回扫码结果用的。
  /// 目前的逻辑是调起扫码功能，根据扫码结果先判断o2oa 内部的业务，如果不是内部，弹出扫码结果，可以复制。
  /// 如果[O2ScanCallback]不为空，则把扫码结果返回给[O2ScanCallback]。
  static Future<void> o2ScanBiz({O2ScanCallback? callback}) async {
    if (await _cameraPermission()) {
      final result = await ScanPage.startScan();
      OLogger.d(result);
      if (result != null && result is String) {
        Uri? uri = Uri.tryParse(result);
        String? meta = uri?.queryParameters['meta'];
        OLogger.d('meta: $meta');
        // 有meta 跳转到扫码登录界面 是pc端扫码登录功能
        if (meta?.isNotEmpty == true) {
          ScanLoginPage.openLogin2Pc(meta!);
          return;
        } else if (uri != null &&
            uri.host ==
                O2ApiManager.instance.centerServerInfo?.webServer?.host) {
          // 内部链接地址 进行特殊处理
          if (result.contains("x_meeting_assemble_control") &&
              result.contains("/checkin")) {
            // 会议签到功能
            final idReg = RegExp(
                r"x_meeting_assemble_control\/jaxrs\/meeting\/(.*?)\/checkin");
            final ids = idReg.allMatches(result);
            if (ids.isNotEmpty) {
              final idMatch = ids.first;
              // 获取会议 id
              String? id = idMatch.group(1);
              if (id != null) {
                final res = await MeetingAssembleService.to.meetingCheckIn(id);
                if (res != null) {
                  Loading.toast('scan_meeting_check_alert_msg'.tr);
                }
                return;
              }
            }
          } else if (result.contains("x_desktop/cmspreview.html") ||
              result.contains("x_desktop/cmsdoc.html") ||
              result.contains("x_desktop/cmsdocMobile.html") ||
              result.contains("x_desktop/cmsdocmobilewithaction.html")) {
            var documentId = uri.queryParameters['documentId'];
            var readonly = uri.queryParameters['readonly'] ?? 'true';
            if (documentId == null || documentId.isEmpty == true) {
              documentId = uri.queryParameters['id'];
            }
            if (documentId != null && documentId.isNotEmpty == true) {
              CmsDocumentPage.open(documentId,
                  title: '', options: {'readonly': readonly});
              return;
            }
          } else if (result.contains("x_desktop/work.html") ||
              result.contains("x_desktop/workmobile.html") ||
              result.contains("x_desktop/workmobilewithaction.html")) {
            var workId = uri.queryParameters['workId'];
            if (workId == null || workId.isEmpty == true) {
              workId = uri.queryParameters['workid'];
            }
            if (workId == null || workId.isEmpty == true) {
              workId = uri.queryParameters['work'];
            }
            if (workId == null || workId.isEmpty == true) {
              workId = uri.queryParameters['workcompletedid'];
            }
            if (workId == null || workId.isEmpty == true) {
              workId = uri.queryParameters['workcompletedId'];
            }
            if (workId == null || workId.isEmpty == true) {
              workId = uri.queryParameters['id'];
            }
            if (workId != null && workId.isNotEmpty == true) {
              ProcessWebviewPage.open(workId,
                  title: 'process_work_no_title_no_process'.tr);
              return;
            }
          } else if (result.contains("x_desktop/portalmobile.html") ||
              result.contains("x_desktop/portal.html")) {
            final portalId = uri.queryParameters['id'];
            final pageId = uri.queryParameters['page'];
            if (portalId != null && portalId.isNotEmpty) {
              PortalPage.open(portalId, title: '', pageId: pageId);
              return;
            }
          } else if (result.contains("x_desktop/app.html") ||
              result.contains("x_desktop/appMobile.html")) {
            final app = uri.queryParameters['app'];
            final status = uri.queryParameters['status'];
            if (app != null &&
                app.isNotEmpty &&
                status != null &&
                status.isNotEmpty) {
              final map = O2Utils.parseStringToJson(status);
              if (app == 'process.Work') {
                String work = map['workId'] ?? '';
                if (work.isEmpty) {
                  work = map['workCompletedId'] ?? '';
                }
                if (work.isNotEmpty) {
                  ProcessWebviewPage.open(work,
                      title: 'process_work_no_title_no_process'.tr);
                  return;
                }
              } else if (app == 'cms.Document') {
                String documentId = map['documentId'] ?? '';
                bool readonly = map['readonly'] ?? true;
                if (documentId.isNotEmpty) {
                  CmsDocumentPage.open(documentId,
                      title: '', options: {'readonly': readonly});
                  return;
                }
              } else if (app == 'portal.Portal') {
                String portalId = map['portalId'] ?? '';
                String pageId = map['pageId'] ?? '';
                if (portalId.isNotEmpty) {
                  PortalPage.open(portalId, title: '', pageId: pageId);
                  return;
                }
              } else if (app == 'Meeting') {
                Get.toNamed(O2OARoutes.appMeeting);
                return;
              } else if (app == 'Calendar') {
                Get.toNamed(O2OARoutes.appCalendar);
                return;
              } else if (app == 'process.TaskCenter') {
                String type = map['navi'] ?? 'task';
                switch (type.toLowerCase()) {
                  case 'task':
                    Get.toNamed(O2OARoutes.appTask);
                    break;
                  case 'taskcompleted':
                    Get.toNamed(O2OARoutes.appTaskcompleted);
                    break;
                  case 'read':
                    Get.toNamed(O2OARoutes.appRead);
                    break;
                  case 'readcompleted':
                    Get.toNamed(O2OARoutes.appReadcompleted);
                    break;
                  default:
                    Get.toNamed(O2OARoutes.appTask);
                    break;
                }
                return ;
              }
            }
          }
        }
        // 其他扫码内容 返回 callback  或者 直接展现
        if (callback != null) {
          callback(result);
        } else {
          _showScanResult(result);
        }
      }
    } else {
      Loading.toast('scan_no_camera_permission'.tr);
      return;
    }
  }

  /// 启动扫码
  static Future<dynamic> startScan() async {
    return await Get.toNamed(O2OARoutes.scan);
  }

  /// 扫码结果复制
  static void _showScanResult(String result) {
    O2UI.showConfirm(Get.context, result, okText: '复制', okPressed: (() {
      Clipboard.setData(ClipboardData(text: result));
      Loading.toast('im_chat_success_copy'.tr);
    }));
  }

  /// 摄像头权限
  static Future<bool> _cameraPermission() async {
    var status = await Permission.camera.status;
    if (status == PermissionStatus.granted) {
      return true;
    } else {
      status = await Permission.camera.request();
      if (status == PermissionStatus.granted) {
        return true;
      }
    }
    return false;
  }

  @override
  _ScanPageState createState() => _ScanPageState();
}

class _ScanPageState extends State<ScanPage>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  var screenHeight = 0.toDouble();
  var top = 0.toDouble();
  Animation<double>? animation;

  @override
  void initState() {
    _controller =
        AnimationController(duration: const Duration(seconds: 3), vsync: this);
    _controller.addStatusListener((status) {
      OLogger.d("动画执行，$status");
    });
    animation = Tween<double>(begin: 0, end: 1).animate(_controller);
    animation?.addListener(() {
      setState(() {});
    });
    super.initState();
    // 开始动画
    _controller.repeat(reverse: true);
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
          child: Stack(children: [
        // 摄像头界面
        const ScannerWidget(),
        // 扫描动画
        _animationWidget(context),
        // 关闭按钮
        Align(
            alignment: Alignment.topLeft,
            child: Padding(
                padding: EdgeInsets.only(left: 16.w, top: 24.h),
                child: IconButton(
                    onPressed: () {
                      Get.back();
                    },
                    icon: const Icon(Icons.close),
                    color: Colors.white,
                    iconSize: 36.w))),
        // 手电筒
        const TorchWidget(),
      ])),
    );
  }

  Widget _animationWidget(BuildContext context) {
    screenHeight = MediaQuery.of(context).size.height;
    top = (animation?.value ?? 0) * screenHeight;
    return Positioned(
        left: 20,
        top: top,
        width: MediaQuery.of(context).size.width - 40,
        height: 2,
        child: Container(decoration: const BoxDecoration(color: Colors.green)));
  }
}

//闪光灯
class TorchWidget extends GetView<ScanController> {
  const TorchWidget({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return GetBuilder<ScanController>(
      builder: (_) {
        return Align(
            alignment: Alignment.bottomRight,
            child: Padding(
                padding: EdgeInsets.only(right: 16.w, bottom: 32.h),
                child: IconButton(
                    onPressed: controller.tapTorch,
                    icon: Obx(() => Icon(controller.state.torchLight
                        ? Icons.flashlight_off_outlined
                        : Icons.flashlight_on_outlined)),
                    color: Colors.white,
                    iconSize: 36.w)));
      },
    );
  }
}

class ScannerWidget extends GetView<ScanController> {
  const ScannerWidget({Key? key}) : super(key: key);

  // 主视图
  Widget _buildView() {
    return MobileScanner(
        allowDuplicates: false,
        controller: controller.scannerController,
        onDetect: (barcode, args) {
          if (barcode.rawValue == null) {
            OLogger.e('扫码失败！');
            Loading.toast('scan_result_empty'.tr);
            Get.back();
          } else {
            final String code = barcode.rawValue!;
            OLogger.d('扫码成功： $code');
            Get.back(result: code);
          }
        });
  }

  @override
  Widget build(BuildContext context) {
    return GetBuilder<ScanController>(
      builder: (_) {
        return _buildView();
      },
    );
  }
}
